export const objectWithShadowShader = /* wgsl */ `
  // Vertex shader

  @group(0) @binding(0)
  var<uniform> modelView: mat4x4<f32>;
  @group(0) @binding(1)
  var<uniform> projection: mat4x4<f32>;
  @group(0) @binding(2)
  var<uniform> normalMatrix: mat4x4<f32>;
  @group(0) @binding(3)
  var<uniform> lightDirection: vec3<f32>;
  @group(0) @binding(4)
  var<uniform> viewDirection: vec3<f32>;

  @group(0) @binding(5)
  var<uniform> ambientColor:vec4<f32>;// = vec4<f32>(0.15, 0.10, 0.10, 1.0);
  @group(0) @binding(6)
  var<uniform> diffuseColor:vec4<f32>;// = vec4<f32>(0.55, 0.55, 0.55, 1.0);
  @group(0) @binding(7)
  var<uniform> specularColor:vec4<f32>;// = vec4<f32>(1.0, 1.0, 1.0, 1.0);

  @group(0) @binding(8)
  var<uniform> shininess:f32;// = 20.0;

  const diffuseConstant:f32 = 1.0;
  const specularConstant:f32 = 1.0;
  const ambientConstant: f32 = 1.0;

  fn specular(lightDir:vec3<f32>, viewDir:vec3<f32>, normal:vec3<f32>,  specularColor:vec3<f32>,
       shininess:f32) -> vec3<f32> {
      let reflectDir:vec3<f32> = reflect(-lightDir, normal);
      let specDot:f32 = max(dot(reflectDir, viewDir), 0.0);
      return pow(specDot, shininess) * specularColor;
  }

  fn diffuse(lightDir:vec3<f32>, normal:vec3<f32>,  diffuseColor:vec3<f32>) -> vec3<f32>{
      return max(dot(lightDir, normal), 0.0) * diffuseColor;
  }

  struct VertexOutput {
      @builtin(position) clip_position: vec4<f32>,
      @location(0) viewDir: vec3<f32>,
      @location(1) normal: vec3<f32>,
      @location(2) lightDir: vec3<f32>,
      @location(3) wldLoc: vec3<f32>,
      @location(4) lightLoc: vec3<f32>,
      @location(5) inPos: vec3<f32>
  };

  @vertex
  fn vs_main(
      @location(0) inPos: vec3<f32>,
      @location(1) inNormal: vec3<f32>
  ) -> VertexOutput {
      var out: VertexOutput;

      out.viewDir = normalize((normalMatrix * vec4<f32>(viewDirection, 0.0)).xyz);
      out.lightDir = normalize((normalMatrix * vec4<f32>(-lightDirection, 0.0)).xyz);
      out.normal = normalize(normalMatrix * vec4<f32>(inNormal, 0.0)).xyz;
      var wldLoc:vec4<f32> = modelView * vec4<f32>(inPos, 1.0);
      out.clip_position = projection * wldLoc;
      out.wldLoc = wldLoc.xyz / wldLoc.w;
      out.inPos = inPos;
      var lightLoc:vec4<f32> = modelView * vec4<f32>(lightDirection, 1.0);
      out.lightLoc = lightLoc.xyz / lightLoc.w;
      return out;
  }

  // Fragment shader
  @group(0) @binding(9)
  var t_depth: texture_depth_2d;
  @group(0) @binding(10)
  var s_depth: sampler_comparison;
  @group(0) @binding(11)
  var<uniform> lightModelViewMatrix: mat4x4<f32>;
  @group(0) @binding(12)
  var<uniform> lightProjectionMatrix: mat4x4<f32>;

  @fragment
  fn fs_main(in: VertexOutput,   @builtin(front_facing) face: bool) -> @location(0) vec4<f32> {
      var lightLoc:vec3<f32> = in.lightLoc;
      var lightDir:vec3<f32> = normalize(in.lightDir);
      var n:vec3<f32> = normalize(in.normal);
      var viewDir: vec3<f32> = in.viewDir;
      var fragmentPosInShadowMapSpace: vec4<f32> = lightProjectionMatrix * lightModelViewMatrix * vec4(in.inPos, 1.0);
      fragmentPosInShadowMapSpace = fragmentPosInShadowMapSpace / fragmentPosInShadowMapSpace.w;
      var depth: f32 = fragmentPosInShadowMapSpace.z;
      var uv:vec2<f32> = 0.5*(fragmentPosInShadowMapSpace.xy + vec2(1.0,1.0));

      var visibility = 0.0;
          let oneOverShadowDepthTextureSize = 1.0 / 1024.0;
          for (var y = -2; y <= 2; y++) {
            for (var x = -2; x <= 2; x++) {
              let offset = vec2<f32>(vec2(x, y)) * oneOverShadowDepthTextureSize;

              visibility += textureSampleCompare(
                  t_depth, s_depth,
                  vec2(uv.x, 1.0-uv.y) + offset,depth  - 0.0003
              );
            }
          }
          visibility /= 25.0;
      if (face) {
          var wldLoc2light:vec3<f32> =   in.wldLoc-lightLoc;
          var align:f32 = dot( normalize(wldLoc2light),lightDir);
          if (align > 0.9) {
              var radiance:vec3<f32>  = ambientColor.rgb * ambientConstant +
                  diffuse(-lightDir, n, diffuseColor.rgb)* diffuseConstant +
                  specular(-lightDir, viewDir, n, specularColor.rgb, shininess) * specularConstant;

              return vec4<f32>(radiance * visibility ,1.0);
              // return vec4<f32>(radiance ,1.0);
              // return vec4<f32>( 0.0,0.0,visibility,1.0);
          }
      }
      return vec4<f32>( 0.0,0.0,0.0,1.0);
  }
`;
